/*
 * Conformer.h
 *
 *  Created on: Jul 6, 2013
 *      Author: x
 */

#ifndef CONFORMER_H_
#define CONFORMER_H_

#include <string>
#include <vector>
#include <map>

#include "Atom.h"


namespace mcce {
class Residue;
class Conformer {
public:
	// pairwise interaction between two conformers.
	class Pairwise {
	public:
		float ele;
		float vdw;
		//float crt;
		//float ori;
		float sumPairwise;
		//std::string  mark;

		Pairwise(float _ele=0.0, float _vdw=0.0, float _sumPairwise=0.0)
		: ele(_ele), vdw(_vdw), sumPairwise(_sumPairwise) {}
	};
private:
	int iConf;
	std::string uniqId;
	std::string confName;  	/* conforname is resName+1st+2nd char in "history" */
	char   hFlag;
	float  netcrg;       	/* net charge */
	float  pKa;          	/* pKa of the acid: HA <=> H+ + A- */
	float  Em;          	 /* Em of the reduced: RED <=> OX + e- */
	float  eTorsion;   	 /* torsion energy */
	float  eVdw0;       	/* VDW potential to its own (including backbone atoms) */
	float  eVdw1;       	/* VDW potential to backbone atoms (excluding its own) */
	float  eEpol;      	 /* elec to backbone */
	float  eTors;
	float  eRxn0;
	float  eRxn;
	float  eExtra;      	/* extra energy to make the calc. match training exep. */
	float  eDsolv;
	float  ePh;
	float  eEh;
	float  eMfe;
	float  eSelf0;      	/* self energy without mfe */
	float  eTS;         	/* entropy of this group of conformers */
	double eSelf;       	/* total self energy, with mfe */
	float  occ;          	/* occupance in head3.lst, it's a fixed value. */
	int    e;            	/* number of electron(s) gained */
	int    H;            	/* number of proton(s) gained */
	std::string   history;  	/* history of making this conformer */

	int    n_atom;			// number of atoms in the conformer
	bool   dummy;

	Residue *inRes;
	std::vector<float> mocc; // occ of mc sampling
	std::map<std::string, Pairwise> pairwise;
	std::vector<Atom> atoms; // atoms in the conformer

public:

	int    counter;      	/* General counter */
	Conformer();
	virtual ~Conformer();

	int loadFromHead3(std::string hLine);       // set a conformer from a line of "head3.lst"

	bool isBelongToRes(Residue &Res);

	bool isSameConfType(const Conformer &conf) const;

	std::map<std::string, Pairwise>& getPairwise() {
		return pairwise;
	}

	const std::map<std::string, Pairwise>& getPairwise() const {
		return pairwise;
	}

	void incrementCounter(int increaseAmount=1) {
		counter += increaseAmount;
	}

	Conformer& addConfInteraction(std::string confUniqID, Pairwise &confPw) {
		pairwise.insert(make_pair(confUniqID, confPw));
		return *this;
	}

	std::string getResName() const {
		return (uniqId.substr(0, 3) + uniqId.substr(5, 5));
	}

	void setInRes(Residue *res) {
		inRes = res;
	}

	Residue* getInRes() {
		return inRes;
	}

	std::vector<float>& getMocc() {
		return mocc;
	}

	int getIConf() const {
		return iConf;
	}

	const std::vector<Atom>& getAtoms() const {
		return atoms;
	}

	void setAtoms(const std::vector<Atom>& atoms) {
		this->atoms = atoms;
	}

	char getHFlag() const {
		return hFlag;
	}

	void setHFlag(char flag) {
		hFlag = flag;
	}

	bool isDummy() const {
		return dummy;
	}

	void setDummy(bool dummy) {
		this->dummy = dummy;
	}

	const std::string& getConfName() const {
		return confName;
	}

	void setConfName(const std::string& confName) {
		this->confName = confName;
	}

	int getCounter() const {
		return counter;
	}

	void setCounter(int counter) {
		this->counter = counter;
	}

	int getE() const {
		return e;
	}

	void setE(int e) {
		this->e = e;
	}

	float getEDsolv() const {
		return eDsolv;
	}

	void setEDsolv(float dsolv) {
		eDsolv = dsolv;
	}

	float getEEh() const {
		return eEh;
	}

	void setEEh(float eh) {
		eEh = eh;
	}

	float getEEpol() const {
		return eEpol;
	}

	void setEEpol(float epol) {
		eEpol = epol;
	}

	float getEExtra() const {
		return eExtra;
	}

	void setEExtra(float extra) {
		eExtra = extra;
	}

	float getEm() const {
		return Em;
	}

	void setEm(float em) {
		Em = em;
	}

	float getEMfe() const {
		return eMfe;
	}

	void setEMfe(float mfe) {
		eMfe = mfe;
	}

	float getEPh() const {
		return ePh;
	}

	void setEPh(float ph) {
		ePh = ph;
	}

	float getERxn() const {
		return eRxn;
	}

	void setERxn(float rxn) {
		eRxn = rxn;
	}

	float getERxn0() const {
		return eRxn0;
	}

	void setERxn0(float rxn0) {
		eRxn0 = rxn0;
	}

	double getESelf() const {
		return eSelf;
	}

	void setESelf(double self) {
		eSelf = self;
	}

	float getESelf0() const {
		return eSelf0;
	}

	void setESelf0(float self0) {
		eSelf0 = self0;
	}

	void setESelf0() {
		eSelf0 = eVdw0 + eVdw1 + eEpol + eTors + eDsolv + eExtra + ePh + eEh + eTS;
	}

	float getETors() const {
		return eTors;
	}

	void setETors(float tors) {
		eTors = tors;
	}

	float getETorsion() const {
		return eTorsion;
	}

	void setETorsion(float torsion) {
		eTorsion = torsion;
	}

	float getETs() const {
		return eTS;
	}

	void setETs(float ts) {
		eTS = ts;
	}

	float getEVdw0() const {
		return eVdw0;
	}

	void setEVdw0(float vdw0) {
		eVdw0 = vdw0;
	}

	float getEVdw1() const {
		return eVdw1;
	}

	void setEVdw1(float vdw1) {
		eVdw1 = vdw1;
	}

	int getH() const {
		return H;
	}

	void setH(int h) {
		H = h;
	}

	const std::string& getHistory() const {
		return history;
	}

	void setHistory(const std::string& history) {
		this->history = history;
	}

	int getConf() const {
		return iConf;
	}

	void setConf(int conf) {
		iConf = conf;
	}

	int getAtom() const {
		return n_atom;
	}

	void setAtom(int atom) {
		n_atom = atom;
	}

	float getNetcrg() const {
		return netcrg;
	}

	void setNetcrg(float netcrg) {
		this->netcrg = netcrg;
	}

	float getOcc() {
		return occ;
	}

	void setOcc(float occ) {
		this->occ = occ;
	}



	float getPKa() const {
		return pKa;
	}

	void setPKa(float ka) {
		pKa = ka;
	}

	const std::string& getUniqId() const {
		return uniqId;
	}

	void setUniqId(const std::string& uniqId) {
		this->uniqId = uniqId;
	}
};

} /* namespace mcce */
#endif /* CONFORMER_H_ */
